<?php
/**
 * @version 1.4.0
 * @author tuadmin
 * @copyright 2011
 * @file tpl
 * --alter code-
 * - type . name : user : description
 * - method . existData : rootciv : for isset this vars internals
 * - method . parse : rootciv : support multilevel
 * - method . render : rootciv : support multilevel
 * - method . getData : rootciv : support default value in second argument
 * - method . getAssing : rootciv : support get values and keys and subkeys
 * - method . __set && __get : rootciv : support getters and setters
 * - constant . TEMPLATE_EXT: tuadmin : deleted
 * - constant . DEFAULT_TEMPLATE_EXT: tuadmin : added
 * - method . setOptiont : tuadmin : added for configuration "tpl"
 */
class tpl
{
	const DEFAULT_TEMPLATE_EXT = '.tpl.php';
	private $_path;
	private $_vars;
	private $_vars_globals;
	private $_parse;
	//private $_render;
	private $_errors;
	//private $_tmp_vars;
	//private $_is_parse = false;
	private $_level = 0;
	private $_levels = array();
	private $_extension = null;
	public $debug_mode = false;
	const OPT_DEBUG_MODE_bool = 1;
	const OPT_TEMPLATE_EXT_string = 2;
	public function __construct($base, $extension = false)
	{
		if(defined("myMain"))
		{
			$this->debug_mode = configuration::$PORTAL["DEBUG_MODE"];
		}

		$this->_path = rtrim ( $base , "/\\" );
		$this->_vars = new ArrayObject ( );
		$this->_vars_globals = new ArrayObject ( );
		$this->_parse = new ArrayObject ( );
		$this->_errors = new ArrayObject ( );
		$this->_extension = $extension ? $extension : self::DEFAULT_TEMPLATE_EXT;

	}
	public function setOption($opt , $value)
	{
		switch($opt)
		{
			case self::OPT_DEBUG_MODE_bool: $this->debug_mode = (bool) $value;break;
			case self::OPT_TEMPLATE_EXT_string: $this->_extension = $value; break;
		}
		return 0;
	}
	/**
	 * @uses iniciate template
	 * @param string $name
	 * @return boolean|string
	 */
	public function parse($name)
	{
		$this->_level++;
		$this->_levels[$this->_level] = $name;
		$name = $this->_levels[$this->_level];

		if(is_file ( $this->_path . "/$name" . $this->_extension ))
		{
			//$this->_vars->offsetSet($name, new ArrayObject());
			/*Se inserta las variables Globales para que esten junto a las*/
			$this->_vars->offsetSet ( $name , new ArrayObject ( ) );
			$this->_parse->offsetSet ( $name , file_get_contents ( $this->_path . "/$name" . $this->_extension ) );
			$this->_levels[$this->_level] = $name;
			return $name;
		}
		else
		{
			if($this->debug_mode == true)
			{
				die ( "404: template <strong>'" . $this->_path . "/$name" . $this->_extension . "'</strong> Not Found " );
			}
			$this->_errors->append ( "404: template <strong>'" . $this->_path . "/$name" . $this->_extension . "'</strong> Not Found " );
			return false;
		}
	}
	/**
	 * @param string $name
	 * @param bool $reuse
	 * @return string|bool
	 */
	public function render($name,$____reuse = false)
	{
		if(!isset($this->_levels[$this->_level]))
		{
			die("Not Initialized \$this->parse()");
		}
		//var_dump($this->_parse);
		$this->_levels[$this->_level] = $name;unset($name);

		//$name =  $this->_levels[$this->_level];
		//$this->_levels[$this->_level] = $name;
	//	if($this->_parse->offsetExists ( $name ))
		if($this->_parse->offsetExists ( $this->_levels[$this->_level] ))
		{
			ob_start ();
			//if(require( $this->_parse->offsetGet ( $name ) . '' ) === false)
			/*//if(eval ( '?>' . $this->_parse->offsetGet ( $name ) . '' ) === false)/**/
			if(eval ( '?>' . $this->_parse->offsetGet ( $this->_levels[$this->_level] ) . '' ) === false)
			{
				echo "Parser ERROR;\n";
				/*die ( $this->debug ( '?>' . $this->_parse->offsetGet ( $name ) ) );*/
				die ( $this->debug ( '?>' . $this->_parse->offsetGet ( $this->_levels[$this->_level] ) ) );
			}
			else
			{
				//if($____reuse){$this->_parse->offsetUnset ( $name );}
				if($____reuse){$this->_parse->offsetUnset (  $this->_levels[$this->_level]  );}
				$this->_vars->offsetUnset ( $this->_levels[$this->_level] );
				$this->_level--;
			}
			//include($this->_template_path."/$_name_uncompile".template::TEMPLATE_EXT);
			//echo $this->_template_path."/$_name_uncompile".template::TEMPLATE_EXT;
			//echo "================================================================";
			//var_dump($this->_parse);
			//$this->_vars->offsetUnset ( $name );
			return ob_get_clean ();
		}
		else
		{
			return false;
		}
	}

	/**
	 * tpl::parseAndRender()
	 *
	 * @param string $tpl_name
	 * @param array $Assigns
	 * @return string
	 */
	public function parseAndRender($tpl_name , $Assigns = array())
	{
		$this->parse($tpl_name);
			$this->exchangeAssigns($Assigns);
		return $this->render($tpl_name);
	}
	/**
	 * change var internals for new in array
	 * @param array $change
	 * @return tpl
	 */
	public function exchangeAssigns($change)
	{
		if(is_array($change))
		{
			$this->_vars->offsetGet( $this->_levels[$this->_level] )->exchangeArray($change);
		}
		return $this;
	}
	public function eraseAssings($name)
	{
		//$this->_vars->offsetset ( $this->_levels[$this->_level],null );
		return $this->_vars->offsetExists($name)?$this->_vars->offsetUnset($name) : null;
	}
	/**
	 * change var internals for new in array
	 * @param array $array
	 * @return tpl
	 */
	public function assigns($array)
	{
		$this->_vars->offsetGet( $this->_levels[$this->_level] )->exchangeArray($array);
		return $this;
	}
	/**
	 * @param string $name
	 * @param mixed $value
	 * @return this
	 */
	public function assign($name , $value = null)
	{
		$this->_vars->offsetGet ( $this->_levels[$this->_level] )->offsetSet ( $name , $value );
		unset($value);
		return $this;
	}
	public function getAssign($name,$key = null,$sub_key = null)
	{
		$data = $this->getData($name);
		if(!is_null($key))
		{
			if(!is_null($sub_key))
			{
				return $data[$key][$sub_key];
			}
			else
			{
				return $data[$key];
			}
		}
		return $data;
	}
	/**
	 * @param string $name
	 * @param mixed $value
	 * @return this
	 */
	public function set($name , $value = null)
	{
		if($value === null)
		{
			return $this->_vars_globals->offsetGet ( $name );
		}
		else
		{
			$this->_vars_globals->offsetSet ( $name , $value );
		}
		return $this;
	}
	private function getAllData()
	{
		if($this->_vars->offsetGet ( $this->_levels[$this->_level] ))
		{
			return $this->_vars->offsetGet ( $this->_levels[$this->_level] )->getArrayCopy();
		}
	}
	/**
	 * @param string|null $name_var
	 * @param bool $return_default
	 * @return string|bool
	 */
	public function & getData($name_var = null,$return_default = false)
	{
		//$return = false;
		if($name_var == null)
		{
			$return = $this->_vars->offsetGet ( $name_var );
		}
		else
		{
			if($this->_vars->offsetGet ( $this->_levels[$this->_level] )->offsetExists ( $name_var ))
			{

				$return = $this->_vars->offsetGet ( $this->_levels[$this->_level] )->offsetGet ( $name_var );
			}
			else
			{
				$return = & $return_default;
			}

		}
		return $return;
	}
	/**
	 * Enter description here ...
	 * @param string $name_var
	 * @return bool
	 */
	public function existData($name_var)
	{
		return  $this->_vars->offsetGet ($this->_levels[$this->_level] )->offsetExists ( $name_var );
	}
	public function existGlobal($name_var)
	{
		return $this->_vars_globals->offsetExists ( $name_var );
	}
	/**
	 * @param string|null $name_var
	 * @return string|bool
	 */
	private function & getGlobals($name_var = null)
	{
		$return = null;
		if($name_var == null)
		{
			$return = $this->_vars_globals;
		}
		else
		{
			if($this->_vars_globals->offsetExists ( $name_var ))
			{
				$return = $this->_vars_globals->offsetGet ( $name_var );
			}
		}
		return $return;
	}
	private function & getD($name_var = null)
	{
		return $this->getData ( $name_var );
	}
	private function & getG($name_var = null)
	{
		return $this->getGlobals ( $name_var );
	}
	public function __get($name_var)
	{
		//echo "<h1>Variables inexistentes</h1>";
		switch(true)
		{
			case $this->_vars_globals->offsetExists ( $name_var ):
				return $this->_vars_globals->offsetGet ( $name_var );
			break;
			case $this->_vars->offsetGet ( $this->_levels[$this->_level] )->offsetExists ( $name_var ) :
				return $this->_vars->offsetGet ( $this->_levels[$this->_level] )->offsetGet ( $name_var );
			default :return null;
		}
	}
	public function __set($name_var,$value)
	{
		$this->_vars_globals->offsetSet ( $name_var , $value );
	}
	/**
	 * @param string $script
	 * @return string
	 */
	private function debug($script)
	{
		$variable = null;
		ob_start ();
		$nivelviejo = error_reporting ( 0 );
		highlight_string ( $script );
		error_reporting ( $nivelviejo );
		$buffer = ob_get_contents ();
		ob_end_clean ();
		if(isset ( $variable ))
		{
			$abrirpost = strpos ( $buffer , '<?' );
			$cerrarpost = strrpos ( $buffer , '?' );
			$buffer = substr ( $buffer , 0 , $abrirpost ) . substr ( $buffer , $abrirpost + 5 , $cerrarpost - ( $abrirpost + 5 ) ) . substr ( $buffer , $cerrarpost + 5 );
		}
		$buffer = explode ( '<br />' , $buffer );
		$buffer = implode ( '</li>' . "\n" . '<li>' , $buffer );
		//$buffer=str_replace('<br \/>',"",$buffer);


		$buffer = preg_replace ( "#(.*?)<br />#" , "<li>$1</li>\n" , $buffer );
		$buffer = "<ol>\n<li>$buffer\n</li>\n</ol>";
		return $buffer;
	}
	public function getErrors()
	{
		return $this->_errors;
	}
}